package com.umeox.watch.moto.chat.ui;


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.AnimationDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;

import com.umeox.moto.common.log.Logger;
import com.umeox.moto.common.utils.AndroidUtils;
import com.umeox.moto.watch.themes.app.ThemeAppCompatActivity;
import com.umeox.moto.watch.themes.widget.TextView;
import com.umeox.watch.moto.chat.BuildConfig;
import com.umeox.watch.moto.chat.R;
import com.umeox.watch.moto.dataservice.constants.Constants;
import com.umeox.watch.moto.dataservice.proxy.PairProxy;

import net.vidageek.mirror.dsl.Mirror;

import java.util.ArrayList;
import java.util.List;

public class PairingActivity extends ThemeAppCompatActivity {
    private static final String TAG = PairingActivity.class.getSimpleName();
    private static final int SHOW_PAIR_RESULT = 0x100;

    private SearchCountDownTimer mSearchCountdown;
    private BluetoothAdapter mBluetoothAdapter;
    private List<BluetoothDevice> deviceList;
    private boolean discoverable, autoDiscover = false;
    private String selfMac;
    private View mTipView;
    private View mAnimView;
    private View mSuccessView;
    private View mFailView;

    private AnimationDrawable pairingAnim;
    private PairProxy pairBinder;
    private boolean isBluetoothEnabledByMyself;

    private TextView mSuccessTips;
    private TextView mFailTips;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();
            if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, 0);
                if (state == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                    Logger.i(TAG, "蓝牙扫描模式变为可见" + state);
                } else if (state == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
                    Logger.i(TAG, "蓝牙扫描模式变为不可见" + state);
                    discoverable = false;
                }

            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                int preState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, 0);
                if (state == BluetoothAdapter.STATE_ON
                        && preState == BluetoothAdapter.STATE_TURNING_ON) {
                    Logger.i(TAG, "蓝牙已打开");
                    if (autoDiscover) {
                        startDiscovery();
                    }
                } else if (state == BluetoothAdapter.STATE_OFF
                        && preState == BluetoothAdapter.STATE_TURNING_OFF) {
                    //测试
                    Logger.i(TAG, "蓝牙已关闭");
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                // 安排在指定的时间执行指定的任务。
                if (!mSearchCountdown.isRunning()) {
                    mSearchCountdown.run();
                    Logger.i(TAG, "收到开始蓝牙搜索广播，开始计时");
                }
            } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // 搜索到的不是已经绑定的蓝牙设备

                final int bondState = device.getBondState();
                if (bondState != BluetoothDevice.BOND_BONDED) {
                    Logger.i(TAG, "搜索到设备 name:" + device.getName() + " address:" + device.getAddress());
                    String name = device.getName();
                    String address = device.getAddress();
                    final boolean checkBluetoothAddress = BluetoothAdapter.checkBluetoothAddress(address);

                    if (!TextUtils.isEmpty(name)
                            && name.startsWith(BuildConfig.PREFIX_BTNAME)
                            && checkBluetoothAddress) {
                        deviceList.add(device);
                    }
                }
                // 搜索完成
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                Logger.i(TAG, "收到蓝牙搜索完成广播");
            } else if (Constants.ACTION_MAKE_FRIEND.equals(action)) {
                int result = intent.getIntExtra(Constants.EXTRA_MAKE_FRIEND_STATUS, 0);
                onPairResult(result);
            }
        }
    };

    private Handler mHandler = new Handler(msg -> {
        if (msg.what == SHOW_PAIR_RESULT) {
            int result = msg.arg1;
            //onPairResult(result);
        }
        return false;
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.act_pairing);
        initView();
        deviceList = new ArrayList<>();
        mSearchCountdown = new SearchCountDownTimer(BuildConfig.BLE_SEARCH_TIMEOUT * 1000, 1000);
    }


    private void initView() {
        mTipView = findViewById(R.id.tip_layout);
        mAnimView = findViewById(R.id.anim_layout);
        mSuccessView = findViewById(R.id.success_layout);
        mFailView = findViewById(R.id.fail_layout);
        mSuccessTips = findViewById(R.id.success_tip_tv);
        mFailTips = findViewById(R.id.tv_fail_tips);

        mTipView.setVisibility(View.VISIBLE);
        mAnimView.setVisibility(View.GONE);
        mSuccessView.setVisibility(View.GONE);
        mFailView.setVisibility(View.GONE);


        android.widget.ImageView ivAnim = findViewById(R.id.ivAnim);
        pairingAnim = (AnimationDrawable) ivAnim.getDrawable();
        findViewById(R.id.btn_start).setOnClickListener(v -> {
            mTipView.setVisibility(View.GONE);
            mAnimView.setVisibility(View.VISIBLE);
            pairingAnim.start();
            startDiscovery();
        });


        findViewById(R.id.btn_retry).setOnClickListener(v -> {
            mTipView.setVisibility(View.GONE);
            mAnimView.setVisibility(View.VISIBLE);
            mSuccessView.setVisibility(View.GONE);
            mFailView.setVisibility(View.GONE);
            if (pairingAnim != null && !pairingAnim.isRunning()) {
                pairingAnim.start();
            }
            startDiscovery();
        });

    }


    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        //注册广播监听
        registerBTReceiver();
        //初始化蓝牙适配器
        enableBluetoothAdapter();
    }


    private void enableBluetoothAdapter() {

        if (mBluetoothAdapter == null) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        // 如果本地蓝牙没有开启，则开启
        isBluetoothEnabledByMyself = mBluetoothAdapter.isEnabled();

        Logger.i(TAG, "当前蓝牙是否开启：" + isBluetoothEnabledByMyself);
        if (!isBluetoothEnabledByMyself) {
            isBluetoothEnabledByMyself = mBluetoothAdapter.enable();
        }
    }

    private void startDiscovery() {
        if (mBluetoothAdapter == null) {
            autoDiscover = true;
            enableBluetoothAdapter();
            return;
        }
        //开启蓝牙可见性
        if (!discoverable) {
            discoverable = setDiscoverable();
        }
        String btName = BuildConfig.PREFIX_BTNAME + "(" + AndroidUtils.getDeviceId() + ")";
        final String bluetoothName = mBluetoothAdapter.getName();
        if (TextUtils.isEmpty(bluetoothName) || !bluetoothName.equals(btName)) {
            final boolean setName = mBluetoothAdapter.setName(btName);
        }
        selfMac = getBtAddressViaReflection(mBluetoothAdapter);
        if (BuildConfig.DEBUG) {
            Logger.i(TAG, "我的蓝牙名称：" + bluetoothName);
            Logger.i(TAG, "我的蓝牙地址：" + selfMac);
        }
        Log.i(TAG, "我的蓝牙名称：" + bluetoothName);
        Log.i(TAG, "我的蓝牙地址：" + selfMac);
        if (mBluetoothAdapter.isDiscovering()) {
            mBluetoothAdapter.cancelDiscovery();
        }
        if (BuildConfig.DEBUG) {
            Logger.i(TAG, "开始搜索");
        }
        //开始搜索
        mBluetoothAdapter.startDiscovery();
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
            finish();
            return true;
        }
        return super.dispatchKeyEvent(event);
    }

    private void cancelDiscovery() {
        if (mBluetoothAdapter == null) {
            return;
        }
        if (mBluetoothAdapter.isDiscovering()) {
            if (BuildConfig.DEBUG) {
                Logger.i(TAG, "停止搜索");
            }
            mBluetoothAdapter.cancelDiscovery();
        }
    }

    private void disableBTAdapter() {
        //关闭蓝牙
        if (isBluetoothEnabledByMyself && mBluetoothAdapter.isEnabled()) {
            Logger.i(TAG, "关闭蓝牙");
            mBluetoothAdapter.disable();
        }
    }

    private void registerBTReceiver() {
        IntentFilter mFilter = new IntentFilter();
        //蓝牙模块被打开或者关闭
        mFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        //注册开始蓝牙搜索receiver
        mFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        //蓝牙模块扫描模式发生了变化
        mFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        // 注册接收到已搜索到的蓝牙设备
        mFilter.addAction(BluetoothDevice.ACTION_FOUND);
        // 注册搜索完时
        mFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        //注册交友结果广播action
        mFilter.addAction(Constants.ACTION_MAKE_FRIEND);
        registerReceiver(mReceiver, mFilter);
    }

    private final List<String> mNearByMacs = new ArrayList<>();

    private void requestPairing() {
        if (pairBinder == null) {
            pairBinder = (PairProxy) PairProxy.fetchBinder();
        }

        AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
            mNearByMacs.clear();
            for (int i = 0; i < deviceList.size(); i++) {
                final String address = deviceList.get(i).getAddress();
                final String name = deviceList.get(i).getName();

                if (!mNearByMacs.contains(address)) {
                    mNearByMacs.add(address);
                }

                Logger.i("requestPairing name:" + name + " address:" + address);
            }

            int result = -1;
            try {
                result = pairBinder.makeFriends(selfMac, mNearByMacs.toArray(new String[]{}));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            Message msg = new Message();
            msg.what = SHOW_PAIR_RESULT;
            msg.arg1 = result;
            mHandler.sendMessage(msg);
        });
    }

    private void onPairResult(int result) {
        Logger.i("交友完成->" + result);
        if (mSearchCountdown != null) {
            mSearchCountdown.stop();
        }
        if (pairingAnim != null && pairingAnim.isRunning()) {
            pairingAnim.stop();
        }

        if (!isFinishing()) {
            boolean success = result == 0;
            mTipView.setVisibility(View.GONE);
            mAnimView.setVisibility(View.GONE);
            String tip;
            if (result == 0) {
                tip = getString(R.string.pairing_success);
            } else if (result == 1) {
                tip = getString(R.string.pairing_exist);
            } else {
                tip = getString(R.string.pairing_failed);
            }
            if (success) {
                mSuccessView.setVisibility(View.VISIBLE);
                mFailView.setVisibility(View.GONE);
                mSuccessTips.setText(tip);
                mSuccessView.postDelayed(this::finish, 2500);
            } else {
                mSuccessView.setVisibility(View.GONE);
                mFailView.setVisibility(View.VISIBLE);
                mFailTips.setText(tip);
                deviceList.clear();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (pairingAnim != null && pairingAnim.isRunning()) {
            pairingAnim.stop();
        }
        if (mSuccessView != null && mSuccessView.getHandler() != null) {
            mSuccessView.getHandler().removeCallbacksAndMessages(null);
        }

        disableBTAdapter();
        if (deviceList != null) {
            deviceList.clear();
            deviceList = null;
        }

        if (mSearchCountdown != null) {
            mSearchCountdown.stop();
        }

        try {
            //解除注册
            unregisterReceiver(mReceiver);
        } catch (Exception ignored) {
        }
    }

    private String getBtAddressViaReflection(BluetoothAdapter mBluetoothAdapter) {
        Object bluetoothManagerService = new Mirror().on(mBluetoothAdapter).get().field("mService");
        if (bluetoothManagerService == null) {
            Logger.e(TAG, "couldn't find bluetoothManagerService");
            return null;
        }
        Object address = null;
        try {
            address = new Mirror().on(bluetoothManagerService).invoke().method("getAddress").withoutArgs();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (address instanceof String) {
            Logger.e(TAG, "using reflection to get the BT MAC address: " + address);
            return (String) address;
        } else {
            return null;
        }
    }

    /**
     * 开启蓝牙可见性
     */
    private boolean setDiscoverable() {
        if (mBluetoothAdapter == null) {
            return false;
        }

        if (BuildConfig.DEBUG) {
            Logger.i(TAG, "设置蓝牙可见");
        }
        try {
            new Mirror().on(mBluetoothAdapter).invoke().method("setDiscoverableTimeout").withArgs(200);
            new Mirror().on(mBluetoothAdapter).invoke().method("setScanMode").withArgs(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, 200);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 关闭蓝牙可见性
     */
    private void closeDiscoverable() {
        if (mBluetoothAdapter == null) {
            return;
        }
        if (BuildConfig.DEBUG) {
            Logger.i(TAG, "设置蓝牙不可见");
        }
        try {
            new Mirror().on(mBluetoothAdapter).invoke().method("setDiscoverableTimeout").withArgs(1);
            new Mirror().on(mBluetoothAdapter).invoke().method("setScanMode").withArgs(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 开启搜索倒计时
     */
    public class SearchCountDownTimer extends CountDownTimer {

        private boolean runFlag = false, sendFlag = false;
        private long millisInFuture = 0;
        private int costTime = 0;//秒

        SearchCountDownTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
            this.millisInFuture = millisInFuture;
        }

        boolean isRunning() {
            return runFlag;
        }

        void run() {
            super.start();
            runFlag = true;
            sendFlag = false;
        }

        void stop() {
            if (runFlag) {
                super.cancel();
                runFlag = false;
            }
        }

        @Override
        public void onFinish() {
            runFlag = false;
            //设置蓝牙设备不可见
            closeDiscoverable();
            //停止蓝牙搜索
            cancelDiscovery();
            onPairResult(-1);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            costTime = (int) ((millisInFuture - millisUntilFinished) / 1000);

            if (!sendFlag && !deviceList.isEmpty() && costTime % 5 == 0) {
                sendFlag = true;
                //停止蓝牙搜索
                cancelDiscovery();
                //发送交友请求后，不能关闭蓝牙，因为对方可能还没有搜索到这台设备
                requestPairing();
            } else if (!sendFlag && costTime > 0 && costTime % 8 == 0) {
                //重新搜索
                startDiscovery();
            }

            if (BuildConfig.DEBUG) {
                Log.i(TAG, "已搜索耗时:" + costTime);
            }
        }
    }

}

